Imports Microsoft.VisualBasic
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports TAPI3Lib
Imports System.Diagnostics
Imports System.Xml
Imports System.Runtime.InteropServices
Imports System.Threading
Imports System.IO
Imports C4F.DevKit.Telephony.Properties
Imports System.Globalization

Namespace C4F.DevKit.Telephony

	''' <summary>
	''' This class provides basic telephony functionality.
	''' </summary>
	Friend Class TapiBase

		#Region "Private Members"

		''' <summary>
		''' TAPI object.
		''' </summary>
		Private tapiObject As TAPIClass = New TAPIClass()

		''' <summary>
		''' List of tokens of the registered lines.
		''' </summary>
		Private registrationTokens As List(Of Integer) = New List(Of Integer)()

		''' <summary>
		''' Represents the currently available calls.
		''' </summary>
		Private availableCalls_Renamed As List(Of CallInfo) = New List(Of CallInfo)()

		''' <summary>
		''' Represents the currently connected call.
		''' </summary>
		Private currentCall_Renamed As CallInfo = Nothing

		''' <summary>
		''' Represents the ITCallInfo interface for current call.
		''' </summary>
		Private iTCurrentCallInfo As ITCallInfo = Nothing

		''' <summary>
		''' Represents the file play back terminal on the current call.
		''' </summary>
		Private playbackTerminal As ITTerminal = Nothing

		''' <summary>
		''' Represents the file recording terminal on the current call.
		''' </summary>
		Private fileRecordingTerminal As ITTerminal = Nothing

		#End Region

		#Region "Constants"

		Private Const DEFAULT_LINE_NAME As String = "Default"

		#End Region

		#Region "Internal Properties"

		''' <summary>
		''' Represents the currently connected call.
		''' </summary>
		Friend ReadOnly Property CurrentCall() As CallInfo

			Get
				Return Me.currentCall_Renamed
			End Get

		End Property

		''' <summary>
		''' Represents the currently available calls.
		''' </summary>
		Friend ReadOnly Property AvailableCalls() As List(Of CallInfo)

			Get
				Return Me.availableCalls_Renamed
			End Get

		End Property

		''' <summary>
		''' Represents the "default" line name
		''' </summary>
		Friend ReadOnly Property DefaultLineName() As String

			Get
				Return DEFAULT_LINE_NAME
			End Get

		End Property

		#End Region

		#Region "Constructors"

		''' <summary>
		''' Initializes a new object of TapiManager.
		''' </summary>
		Friend Sub New()
			InitializeTapi()
		End Sub

		#End Region

		#Region "Delegates and Events"

		''' <summary>
		''' Delegate to handle the incoming and outgoing call event.
		''' </summary>
		''' <param name="callInfo">Information about the call which initiated the event.</param>
		Friend Delegate Sub CallNotificationEventHandler(ByVal callInfo As CallInfo)

		''' <summary>
		''' This event is raised when there is an incoming call.
		''' </summary>
		Friend Event OnIncomingCall As CallNotificationEventHandler

		''' <summary>
		''' This event is raised when there is an outging call.
		''' </summary>
		Friend Event OnOutgoingCall As CallNotificationEventHandler

		''' <summary>
		''' This event is raised when a call has been connected.
		''' </summary>
		Friend Event OnCallConnected As CallNotificationEventHandler

		''' <summary>
		''' This event is raised when a call has been disconnected.
		''' </summary>
		Friend Event OnCallDisconnected As CallNotificationEventHandler

		''' <summary>
		''' This event is raised when a call is placed on hold.
		''' </summary>
		Friend Event OnCallHold As CallNotificationEventHandler

		''' <summary>
		''' Delegate to handle the digit event.
		''' </summary>
		''' <param name="callInfo">Information about the call which initiated the digit event.</param>
		''' <param name="digit">Received digit.</param>
		Friend Delegate Sub DigitNotificationEventHandler(ByVal callInfo As CallInfo, ByVal digit As Char)

		''' <summary>
		''' This event is raised when a digit is received.
		''' </summary>
		Friend Event OnDigitReceived As DigitNotificationEventHandler

		''' <summary>
		''' Delegate to handle the end of playback file event.
		''' </summary>
		''' <param name="callInfo">Information about the call on which the file was being played.</param>
		Friend Delegate Sub EndOfPlaybackNotificationEventHandler(ByVal callInfo As CallInfo)

		''' <summary>
		''' This event is raised when the end of playback file event is generated.
		''' </summary>
		Friend Event OnEndOfFilePlayback As EndOfPlaybackNotificationEventHandler

		#End Region

		#Region "Internal Methods"

		''' <summary>
		''' Gets the communication lines that are currently available.
		''' </summary>
		''' <returns>List of available lines with audio support.</returns>
		Friend Function GetAvailableLines() As List(Of Line)
			Dim lines As List(Of Line) = New List(Of Line)()
			Dim line As Line = Nothing
			Dim iTAddresses As List(Of ITAddress) = GetAddressLines()

			Try
				For Each iAddress As ITAddress In iTAddresses
					Dim iCapabilities As ITAddressCapabilities = CType(iAddress, ITAddressCapabilities)

					' Check if it supports phone number.
					If (iCapabilities.AddressCapability(ADDRESS_CAPABILITY.AC_ADDRESSTYPES) And 1) = 1 Then
						' Check if it supports audio.
						If TapiBase.CheckLineForAudioSupport(iAddress) Then
							line = New Line()
							line.lineName_Renamed = iAddress.AddressName
							Dim iMedia As ITMediaSupport = CType(iAddress, ITMediaSupport)
							line.supportedMediaTypes_Renamed = CType(iMedia.MediaTypes, TapiMediaType)
							line.maxCallsOnHold_Renamed = iCapabilities.AddressCapability(ADDRESS_CAPABILITY.AC_MAXONHOLDCALLS)
							If iCapabilities.AddressCapability(ADDRESS_CAPABILITY.AC_GENERATEDIGITSUPPORT) <> 0 AndAlso iCapabilities.AddressCapability(ADDRESS_CAPABILITY.AC_MONITORDIGITSUPPORT) <> 0 Then
								line.isDtmfSupported_Renamed = True
							Else
								line.isDtmfSupported_Renamed = False
							End If
                            lines.Add(line)
						End If
					End If
				Next iAddress
			Catch exception As Exception
                Throw New TapiManagerException(Resources.ComException, exception)
			End Try
			Return lines
		End Function

		''' <summary>
		''' Gets the communication lines that are currently available.
		''' </summary>
		''' <param name="withDefault">Whether or not to include "default" line</param>
		''' <returns>List of available lines with audio support.</returns>
		Friend Function GetAvailableLines(ByVal withDefault As Boolean) As List(Of Line)
			Dim lines As List(Of Line) = GetAvailableLines()

			If withDefault Then
				Dim defaultLine As Line = New Line()
				defaultLine.lineName_Renamed = DEFAULT_LINE_NAME
				lines.Insert(0, defaultLine)
			End If

			Return lines
		End Function

		''' <summary>
		''' Makes a call to the specified phone number using the specified address line.
		''' </summary>
		''' <param name="targetAddress">Phone number to be dialed.</param>
		''' <param name="lineName">Name of the line to be used to make the call.</param>
		Friend Sub MakeCall(ByVal targetAddress As String, ByVal lineName As String)
			If String.IsNullOrEmpty(targetAddress) Then
				Throw New ArgumentNullException("targetAddress")
			End If

			If String.IsNullOrEmpty(lineName) Then
				Throw New ArgumentNullException("lineName")
			End If

			If lineName.Equals(DefaultLineName) Then
				MakeCall(targetAddress)
			End If

			If Not Me.iTCurrentCallInfo Is Nothing Then
				Throw New InvalidOperationException(Resources.CallAlreadyConnected)
			End If

			Dim iTAddress As ITAddress = GetLineObject(lineName)
			If iTAddress Is Nothing Then
				Throw New TapiManagerException(Resources.SpecifiedLineNotAvailable)
			End If

			If (Not CheckLineForAudioSupport(iTAddress)) Then
				Throw New TapiManagerException(Resources.NoAudioSupport)
			End If
			Try
				' Create call.
				Dim iTBasicCallControl As ITBasicCallControl = CType(iTAddress.CreateCall(targetAddress, TapiConstants.LINEADDRESSTYPE_PHONENUMBER, TapiConstants.TAPIMEDIATYPE_AUDIO), ITBasicCallControl)
				iTBasicCallControl.SetQOS(TapiConstants.TAPIMEDIATYPE_AUDIO, QOS_SERVICE_LEVEL.QSL_BEST_EFFORT)
				' Select terminals.
				TapiBase.SelectMediaTerminals(iTBasicCallControl, iTAddress)
				' Connect.
				iTBasicCallControl.Connect(True)
			Catch exception As Exception
				Throw New TapiManagerException(Resources.ComException, exception)
			End Try
		End Sub

		''' <summary>
		''' Makes a call to the specified phone number.
		''' </summary>
		''' <param name="targetAddress">Phone number to be dialed.</param>
		Friend Sub MakeCall(ByVal targetAddress As String)
			If String.IsNullOrEmpty(targetAddress) Then
				Throw New ArgumentNullException("targetAddress")
			End If

			If Not Me.iTCurrentCallInfo Is Nothing Then
				Throw New InvalidOperationException(Resources.CallAlreadyConnected)
			End If

			' Get the available address lines with audio support.
			Dim addressLines As List(Of Line) = GetAvailableLines()

			Dim callInitiated As Boolean = False
			For Each addressLine As Line In addressLines
				Dim iTAddress As ITAddress = GetLineObject(addressLine.lineName_Renamed)
				Try
					' Create call.
					Dim iTBasicCallControl As ITBasicCallControl = CType(iTAddress.CreateCall(targetAddress, TapiConstants.LINEADDRESSTYPE_PHONENUMBER, TapiConstants.TAPIMEDIATYPE_AUDIO), ITBasicCallControl)
					iTBasicCallControl.SetQOS(TapiConstants.TAPIMEDIATYPE_AUDIO, QOS_SERVICE_LEVEL.QSL_BEST_EFFORT)
					' Select terminals.
					TapiBase.SelectMediaTerminals(iTBasicCallControl, iTAddress)
					' Connect.
					iTBasicCallControl.Connect(True)
					callInitiated = True
				Catch
					' If exception then check another address line.
					Continue For
				End Try
				' If no exception then call is placed successfully.
				Exit For
			Next addressLine
			If (Not callInitiated) Then
				Throw New TapiManagerException(Resources.ErrorCalling)
			End If
		End Sub

		''' <summary>
		''' Answers the latest incoming call.
		''' </summary>
		Friend Sub AnswerCall()
			If Me.availableCalls_Renamed.Count = 0 Then
				Throw New InvalidOperationException(Resources.NoIncomingCall)
			End If

			If Not Me.iTCurrentCallInfo Is Nothing Then
				Throw New InvalidOperationException(Resources.CallAlreadyConnected)
			End If

			Dim isIncomingCall As Boolean = False
			For i As Integer = Me.availableCalls_Renamed.Count - 1 To 0 Step -1
				' Get the latest call from the list having the state as offering.
				If Me.availableCalls_Renamed(i).callState_Renamed = CallState.Offering Then
					isIncomingCall = True
					Dim iTCallInfo As ITCallInfo = ConvertToCallInfoObject(Me.availableCalls_Renamed(i))
					If iTCallInfo Is Nothing Then
						Throw New InvalidOperationException(Resources.NoIncomingCall)
					End If
					Try
						Dim iTBasicCallControl As ITBasicCallControl = CType(iTCallInfo, ITBasicCallControl)
						Dim iTAddress As ITAddress = GetLineObject(Me.availableCalls_Renamed(i).lineName_Renamed)
						' Select terminals.
						TapiBase.SelectMediaTerminals(iTBasicCallControl, iTAddress)
						' Answer the call.
						iTBasicCallControl.Answer()
						Exit Try
					Catch exception As Exception
						Throw New TapiManagerException(Resources.ComException, exception)
					End Try
				End If
			Next i
			If isIncomingCall = False Then
				Throw New InvalidOperationException(Resources.NoIncomingCall)
			End If
		End Sub

		''' <summary>
		''' Answers an incoming call.
		''' </summary>
		''' <param name="call">Call to be answered.</param>
		Friend Sub AnswerCall(ByVal [call] As CallInfo)
			If [call] Is Nothing Then
				Throw New ArgumentNullException("call")
			End If

			If Not Me.iTCurrentCallInfo Is Nothing Then
				Throw New InvalidOperationException(Resources.CallAlreadyConnected)
			End If

			If Me.availableCalls_Renamed.Count = 0 Then
				Throw New ArgumentException(Resources.InvalidCall)
			End If

			Dim IsIncomingCall As Boolean = False

			For i As Integer = 0 To Me.availableCalls_Renamed.Count - 1
				If Me.availableCalls_Renamed(i).hashCode = [call].hashCode Then
					If Me.availableCalls_Renamed(i).callState_Renamed = CallState.Offering AndAlso Me.availableCalls_Renamed(i).lineName_Renamed = [call].lineName_Renamed Then
						IsIncomingCall = True
						Dim iTCallInfo As ITCallInfo = ConvertToCallInfoObject([call])
						If iTCallInfo Is Nothing Then
							Throw New ArgumentException(Resources.InvalidCall)
						End If

						Try
							Dim iTBasicCallControl As ITBasicCallControl = CType(iTCallInfo, ITBasicCallControl)
							Dim iTAddress As ITAddress = GetLineObject(Me.availableCalls_Renamed(i).lineName_Renamed)
							' Select terminals.
							TapiBase.SelectMediaTerminals(iTBasicCallControl, iTAddress)
							' Answer the call.
							iTBasicCallControl.Answer()
							Exit Try
						Catch exception As Exception
							Throw New TapiManagerException(Resources.ComException, exception)
						End Try
					End If
				End If
			Next i
			If IsIncomingCall = False Then
				Throw New ArgumentException(Resources.InvalidCall)
			End If
		End Sub

		''' <summary>
		''' Disconnects the current connected call.
		''' </summary>
		Friend Sub DisconnectCall()
			If Me.iTCurrentCallInfo Is Nothing Then
				Throw New InvalidOperationException(Resources.CallNotConnected)
			End If

			Try
				Dim iTBasicCallControl As ITBasicCallControl = CType(Me.iTCurrentCallInfo, ITBasicCallControl)
				TapiBase.UnselectMediaTerminals(iTBasicCallControl, Me.iTCurrentCallInfo.Address)
				iTBasicCallControl.Disconnect(DISCONNECT_CODE.DC_NORMAL)
			Catch tapiManagerException As TapiManagerException
				' If thrown by other method.
				Throw New TapiManagerException(Resources.ComException, tapiManagerException.InnerException)
			Catch exception As Exception
				Throw New TapiManagerException(Resources.ComException, exception)
			End Try
		End Sub

		''' <summary>
		''' Puts the current call on hold.
		''' </summary>
		''' <returns>True if the method succeeds.</returns>
		Friend Function Hold() As Boolean
			If Me.iTCurrentCallInfo Is Nothing Then
				Throw New InvalidOperationException(Resources.ErrorPuttingOnHold)
			End If

			If Me.iTCurrentCallInfo.CallState = CALL_STATE.CS_HOLD Then
				Throw New InvalidOperationException(Resources.CallAlreadyOnHold)
			End If

			If Me.iTCurrentCallInfo.CallState <> CALL_STATE.CS_CONNECTED Then
				Throw New InvalidOperationException(Resources.CurrentCallNotConnected)
			End If

			Try
				Dim iTBasicCallControl As ITBasicCallControl = CType(Me.iTCurrentCallInfo, ITBasicCallControl)

				' Stop the stream before putting it on hold.
				TapiBase.StartStream(iTBasicCallControl, Me.iTCurrentCallInfo.Address, False)

				'Put the call on hold.
				iTBasicCallControl.Hold(True)
			Catch
				' Return false if unsuccessful.
				Return False
			End Try
			Return True
		End Function

		''' <summary>
		''' Resumes the current call which is on hold.
		''' </summary>
		''' <returns>True if the method succeeds.</returns>
		Friend Function [Resume]() As Boolean
			If Me.iTCurrentCallInfo Is Nothing Then
				Throw New InvalidOperationException(Resources.ErrorNoCallOnHold)
			End If

			If Me.iTCurrentCallInfo.CallState <> CALL_STATE.CS_HOLD Then
				Throw New InvalidOperationException(Resources.ErrorNoCallOnHold)
			End If

			Try
				Dim iTBasicCallControl As ITBasicCallControl = CType(Me.iTCurrentCallInfo, ITBasicCallControl)
				TapiBase.StartStream(iTBasicCallControl, Me.iTCurrentCallInfo.Address, True)
				' Resume the call.
				iTBasicCallControl.Hold(False)
			Catch
				' Return False if unsuccessful.
				Return False
			End Try
			Return True
		End Function

		''' <summary>
		''' Starts the Digit Detection on currently connected call.
		''' </summary>
		Friend Sub StartDigitDetection()
			If Me.iTCurrentCallInfo Is Nothing Then
				Throw New InvalidOperationException(Resources.CallNotConnected)
			End If

			Dim iCapabilities As ITAddressCapabilities = CType(Me.iTCurrentCallInfo.Address, ITAddressCapabilities)
			If iCapabilities.AddressCapability(ADDRESS_CAPABILITY.AC_GENERATEDIGITSUPPORT) <> 0 AndAlso iCapabilities.AddressCapability(ADDRESS_CAPABILITY.AC_MONITORDIGITSUPPORT) <> 0 Then
				Try
					Dim iTLegacyCallMediaControl As ITLegacyCallMediaControl = CType(Me.iTCurrentCallInfo, ITLegacyCallMediaControl)
					iTLegacyCallMediaControl.DetectDigits(TapiConstants.LINEDIGITMODE_DTMF)
				Catch exception As Exception
					Throw New TapiManagerException(Resources.ComException, exception)
				End Try
			Else
				Throw New InvalidOperationException(Resources.NoDtmfSupport)
			End If
		End Sub

		''' <summary>
		''' Stops the Digit Detection on currently connected call.
		''' </summary>
		Friend Sub StopDigitDetection()
			If Me.iTCurrentCallInfo Is Nothing Then
				Throw New InvalidOperationException(Resources.CallNotConnected)
			End If

			Dim iCapabilities As ITAddressCapabilities = CType(Me.iTCurrentCallInfo.Address, ITAddressCapabilities)
			If iCapabilities.AddressCapability(ADDRESS_CAPABILITY.AC_GENERATEDIGITSUPPORT) <> 0 AndAlso iCapabilities.AddressCapability(ADDRESS_CAPABILITY.AC_MONITORDIGITSUPPORT) <> 0 Then
				Try
					Dim iTLegacyCallMediaControl As ITLegacyCallMediaControl = CType(Me.iTCurrentCallInfo, ITLegacyCallMediaControl)
					iTLegacyCallMediaControl.DetectDigits(0)
				Catch exception As Exception
					Throw New TapiManagerException(Resources.ComException, exception)
				End Try
			Else
				Throw New InvalidOperationException(Resources.NoDtmfSupport)
			End If
		End Sub

		''' <summary>
		''' This method causes digits to be output on the current call. Valid digits are 0 through 9, '*', '#', 'A', 'B', 'C', and 'D'.
		''' </summary>
		Friend Sub GenerateDigits(ByVal digits As String)
			If Me.iTCurrentCallInfo Is Nothing Then
				Throw New InvalidOperationException(Resources.CallNotConnected)
			End If

			Dim iCapabilities As ITAddressCapabilities = CType(Me.iTCurrentCallInfo.Address, ITAddressCapabilities)
			If iCapabilities.AddressCapability(ADDRESS_CAPABILITY.AC_GENERATEDIGITSUPPORT) <> 0 AndAlso iCapabilities.AddressCapability(ADDRESS_CAPABILITY.AC_MONITORDIGITSUPPORT) <> 0 Then
				Try
					Dim iTLegacyCallMediaControl As ITLegacyCallMediaControl = CType(Me.iTCurrentCallInfo, ITLegacyCallMediaControl)
					iTLegacyCallMediaControl.GenerateDigits(digits, TapiConstants.LINEDIGITMODE_DTMF)
				Catch exception As Exception
					Throw New TapiManagerException(Resources.ComException, exception)
				End Try
			Else
				Throw New InvalidOperationException(Resources.NoDtmfSupport)
			End If
		End Sub

		''' <summary>
		''' Plays Specified audio files on the current call.
		''' </summary>
		''' <param name="filePaths">List of file paths to play.</param>
		Friend Sub PlayFiles(ByVal filePaths As List(Of String))
			For Each filePath As String In filePaths
				If (Not File.Exists(filePath)) Then
					Throw New ArgumentException(String.Format(CultureInfo.InvariantCulture, Resources.FileNotFound, filePath))
				Else
					Dim fileInfo As FileInfo = New FileInfo(filePath)
					If (Not fileInfo.Extension.Equals(".WAV", StringComparison.InvariantCultureIgnoreCase)) Then
						Throw New ArgumentException(Resources.SupportedFileType)
					End If
				End If
			Next filePath

			If Me.iTCurrentCallInfo Is Nothing Then
				Throw New InvalidOperationException(Resources.CallNotConnected)
			End If

			If Me.iTCurrentCallInfo.CallState <> CALL_STATE.CS_CONNECTED Then
				Throw New InvalidOperationException(Resources.CallNotConnected)
			End If

			Try
				Dim iTBasicCallControl2 As ITBasicCallControl2 = CType(Me.iTCurrentCallInfo, ITBasicCallControl2)

				' Unselect Static Render terminal if already selected.
				TapiBase.UnselectStaticRenderTerminal(CType(Me.iTCurrentCallInfo, ITBasicCallControl), Me.iTCurrentCallInfo.Address)
				' Unselect Static Capture terminal if already selected.
				TapiBase.UnselectStaticCaptureTerminal(CType(Me.iTCurrentCallInfo, ITBasicCallControl), Me.iTCurrentCallInfo.Address)

				If Not Me.playbackTerminal Is Nothing Then
					' Unselect the playback terminal if already selected.
					iTBasicCallControl2.UnselectTerminalOnCall(Me.playbackTerminal)
					Me.playbackTerminal = Nothing
				End If
				Me.playbackTerminal = iTBasicCallControl2.RequestTerminal(TapiConstants.CLSID_String_FilePlaybackTerminal, TapiConstants.TAPIMEDIATYPE_AUDIO, TERMINAL_DIRECTION.TD_CAPTURE)

				Dim mediaPlayback As ITMediaPlayback
				If Not Me.playbackTerminal Is Nothing Then
					mediaPlayback = CType(Me.playbackTerminal, ITMediaPlayback)
					Dim playList As Object() = New Object(filePaths.Count - 1){}

					For i As Integer = 0 To filePaths.Count - 1
						playList(i) = filePaths(i)
					Next i
					mediaPlayback.PlayList = playList
					iTBasicCallControl2.SelectTerminalOnCall(Me.playbackTerminal)
					Dim mediaControl As ITMediaControl = CType(Me.playbackTerminal, ITMediaControl)
					mediaControl.Start()
				End If
			Catch exception As Exception
				Throw New TapiManagerException(Resources.ComException, exception)
			End Try
		End Sub

		''' <summary>
		''' Plays Specified audio file on the current call.
		''' </summary>
		''' <param name="filePath">Path of the audio file to play.</param>
		Friend Sub PlayFile(ByVal filePath As String)
			If filePath Is Nothing Then
				Throw New ArgumentNullException("filePath")
			End If
			If filePath.Equals(String.Empty) Then
				Throw New ArgumentException(Resources.FilePathNotSupplied)
			End If

			If File.Exists(filePath) Then
				Dim filePaths As List(Of String) = New List(Of String)()
				filePaths.Add(filePath)
				PlayFiles(filePaths)
			Else
				Throw New ArgumentException(String.Format(CultureInfo.InvariantCulture, Resources.FileNotFound, filePath))
			End If
		End Sub

		''' <summary>
		''' Stops the file playingon the current call.
		''' </summary>
		Friend Sub StopPlayingFile()
			If Me.iTCurrentCallInfo Is Nothing Then
				Throw New InvalidOperationException(Resources.CallNotConnected)
			End If

			If Not Me.playbackTerminal Is Nothing Then
				Try
					Dim iTBasicCallControl2 As ITBasicCallControl2 = CType(Me.iTCurrentCallInfo, ITBasicCallControl2)
					Dim mediaControl As ITMediaControl = CType(Me.playbackTerminal, ITMediaControl)
					mediaControl.Stop()
					iTBasicCallControl2.UnselectTerminalOnCall(Me.playbackTerminal)
					Me.playbackTerminal = Nothing
				Catch exception As Exception
					Throw New TapiManagerException(Resources.ComException, exception)
				End Try
			Else
				Throw New InvalidOperationException(Resources.NoPlaybackInProgress)
			End If
		End Sub

		''' <summary>
		''' Records the current call and saves with the specified file name. 
		''' </summary>
		Friend Sub RecordCall(ByVal saveFilePath As String)
			If Me.iTCurrentCallInfo Is Nothing Then
				Throw New InvalidOperationException(Resources.CallNotConnected)
			End If

			If saveFilePath Is Nothing Then
				Throw New ArgumentNullException("saveFilePath")
			End If
			If saveFilePath.Equals(String.Empty) Then
				Throw New ArgumentException(Resources.TargetPathNotSupplied)
			End If

			Try
				Dim fs As FileStream = File.Create(saveFilePath)
				fs.Close()
			Catch
				Throw New ArgumentException(Resources.FileCreationError)
			End Try
			Try
				Dim iTBasicCallControl2 As ITBasicCallControl2 = CType(Me.iTCurrentCallInfo, ITBasicCallControl2)

				' Unselect Static Render terminal if already selected.
				TapiBase.UnselectStaticRenderTerminal(CType(Me.iTCurrentCallInfo, ITBasicCallControl), Me.iTCurrentCallInfo.Address)
				' Unselect Static Capture terminal if already selected.
				TapiBase.UnselectStaticCaptureTerminal(CType(Me.iTCurrentCallInfo, ITBasicCallControl), Me.iTCurrentCallInfo.Address)

				If Not Me.playbackTerminal Is Nothing Then
					' Unselect the playback terminal if already selected.
					iTBasicCallControl2.UnselectTerminalOnCall(Me.playbackTerminal)
					Me.playbackTerminal = Nothing
				End If

				If Not Me.fileRecordingTerminal Is Nothing Then
					' Unselect the file recording terminal if already selected.
					iTBasicCallControl2.UnselectTerminalOnCall(Me.fileRecordingTerminal)
					Me.fileRecordingTerminal = Nothing
				End If

				Me.fileRecordingTerminal = iTBasicCallControl2.RequestTerminal(TapiConstants.CLSID_String_FileRecordingTerminal, TapiConstants.TAPIMEDIATYPE_AUDIO, TERMINAL_DIRECTION.TD_RENDER)

				If Not Me.fileRecordingTerminal Is Nothing Then
					Dim iTMediaRecord As ITMediaRecord = CType(Me.fileRecordingTerminal, ITMediaRecord)
					iTMediaRecord.FileName = saveFilePath

					iTBasicCallControl2.SelectTerminalOnCall(Me.fileRecordingTerminal)
					Dim mediaControl As ITMediaControl = CType(Me.fileRecordingTerminal, ITMediaControl)
					mediaControl.Start()
				End If
			Catch exception As Exception
				Throw New TapiManagerException(Resources.ComException, exception)
			End Try
		End Sub

		''' <summary>
		''' Stops the recording of the current call.
		''' </summary>
		Friend Sub StopCallRecording()
			If Me.iTCurrentCallInfo Is Nothing Then
				Throw New InvalidOperationException(Resources.CallNotConnected)
			End If

			If Not Me.fileRecordingTerminal Is Nothing Then
				Try
					Dim iTBasicCallControl2 As ITBasicCallControl2 = CType(Me.iTCurrentCallInfo, ITBasicCallControl2)
					Dim mediaControl As ITMediaControl = CType(Me.fileRecordingTerminal, ITMediaControl)
					mediaControl.Stop()
					iTBasicCallControl2.UnselectTerminalOnCall(Me.fileRecordingTerminal)
					Me.fileRecordingTerminal = Nothing
				Catch exception As Exception
					Throw New TapiManagerException(Resources.ComException, exception)
				End Try
			Else
				Throw New InvalidOperationException(Resources.CallRecordingNotInProgress)
			End If
		End Sub

		''' <summary>
		''' Unregisters all the registered lines and then ends the TAPI session.
		''' </summary>
		Friend Sub TapiShutdown()
			Try
                RemoveHandler tapiObject.ITTAPIEventNotification_Event_Event, AddressOf [Event]
				For Each token As Integer In Me.registrationTokens
					Me.tapiObject.UnregisterNotifications(token)
				Next token
				Me.tapiObject.Shutdown()
			Catch exception As Exception
				Throw New TapiManagerException(Resources.ComException, exception)
			End Try
		End Sub

		#End Region

		#Region "Private Methods"

		''' <summary>
		''' Initializes the tapi session.
		''' </summary>
		Private Sub InitializeTapi()
			Try
				Me.currentCall_Renamed = Nothing
				Me.iTCurrentCallInfo = Nothing
				Me.registrationTokens = New List(Of Integer)()
				Me.availableCalls_Renamed = New List(Of CallInfo)()

				' Initialize TAPI.
				Me.tapiObject.Initialize()

				' Get Available address lines.
				Dim iTAddresses As List(Of ITAddress) = GetAddressLines()

				For Each iTAddress As ITAddress In iTAddresses
					' Check whether is supports Audio.
					If TapiBase.CheckLineForAudioSupport(iTAddress) Then
						' Register for call notification events.
						RegisterLineForIncomingCalls(iTAddress)
					End If
				Next iTAddress

                AddHandler tapiObject.ITTAPIEventNotification_Event_Event, AddressOf [Event]

				' Specify which events it must receive. Sets the event filter mask.
				Me.tapiObject.EventFilter = CInt(Fix(TAPI_EVENT.TE_CALLNOTIFICATION Or TAPI_EVENT.TE_CALLSTATE Or TAPI_EVENT.TE_DIGITEVENT Or TAPI_EVENT.TE_GATHERDIGITS Or TAPI_EVENT.TE_FILETERMINAL))
			Catch tapiManagerException As TapiManagerException
				' If thrown by other method.
				Throw New TapiManagerException(Resources.ComException, tapiManagerException.InnerException)
			Catch exception As Exception
				Throw New TapiManagerException(Resources.ComException, exception)
			End Try
		End Sub

		''' <summary>
		''' Starts or stops the streams.
		''' </summary>
		''' <param name="iTBasicCallControl">ITBasicCallControl interface.</param>
		''' <param name="iTAddress">ITAddress interface.</param>
		''' <param name="start">If true, then it starts the streams else stops the streams.</param>
		''' <returns>True if the method succeeds.</returns>
		Private Shared Function StartStream(ByVal iTBasicCallControl As ITBasicCallControl, ByVal iTAddress As ITAddress, ByVal start As Boolean) As Boolean
			Try
				' Start the streams.
				Dim iEnumStream As IEnumStream = Nothing
				Dim iTStreamControl As ITStreamControl = Nothing

				iTStreamControl = CType(iTBasicCallControl, ITStreamControl)

				If start Then
					TapiBase.SelectMediaTerminals(iTBasicCallControl, iTAddress)
				Else
					TapiBase.UnselectMediaTerminals(iTBasicCallControl, iTAddress)
				End If

				iTStreamControl.EnumerateStreams(iEnumStream)
				Dim iTStream As ITStream = Nothing
				Dim streamsFetched As UInteger = 0

				iEnumStream.Next(1, iTStream, streamsFetched)
				If start Then
					iTStream.StartStream()
				Else
					iTStream.StopStream()
				End If

				iEnumStream.Next(1, iTStream, streamsFetched)
				If start Then
					iTStream.StartStream()
				Else
					iTStream.StopStream()
				End If
			Catch
				Return False
			End Try
			Return True
		End Function

		''' <summary>
		''' Gets the list of ITAddress interfaces based on the currently available address lines.
		''' </summary>
		''' <returns>List of ITAddress interfaces.</returns>
		Private Function GetAddressLines() As List(Of ITAddress)
			Dim iTAddresses As List(Of ITAddress) = New List(Of ITAddress)()
			Try
				' Enumerate the addresses that are currently available.
				Dim enumAddresses As TAPI3Lib.IEnumAddress = Me.tapiObject.EnumerateAddresses()
				Dim iTAddress As ITAddress
				Dim linesFetched As UInteger = 0
				Do
					enumAddresses.Next(1, iTAddress, linesFetched)
					If iTAddress Is Nothing Then
						Exit Do
					End If
					iTAddresses.Add(iTAddress)
				Loop
			Catch exception As Exception
				Throw New TapiManagerException(Resources.ComException, exception)
			End Try

			Return iTAddresses
		End Function

		''' <summary>
		''' Gets the ITAddress interface based on the specified line name.
		''' </summary>
		''' <param name="lineName">Name of the line.</param>
		''' <returns>ITAddress interface if match found, else returns null.</returns>
		Private Function GetLineObject(ByVal lineName As String) As ITAddress
			Dim iTAddresses As List(Of ITAddress) = GetAddressLines()
			For Each iTAddress As ITAddress In iTAddresses
				If String.Compare(iTAddress.AddressName, lineName, StringComparison.InvariantCultureIgnoreCase) = 0 Then
					Return iTAddress
				End If
			Next iTAddress
			Return Nothing
		End Function

		''' <summary>
		''' Checks a line for audio support.
		''' </summary>
		''' <param name="iTAddress">ITAddress interface of the line to be checked.</param>
		''' <returns>True, if line supports audio.</returns>
		Private Shared Function CheckLineForAudioSupport(ByVal iTAddress As ITAddress) As Boolean
			Try
				' Check whether the address line supports audio.
				Dim iMediaSupport As ITMediaSupport = CType(iTAddress, ITMediaSupport)
				Return iMediaSupport.QueryMediaType(TapiConstants.TAPIMEDIATYPE_AUDIO)
			Catch
				Return False
			End Try
		End Function

		''' <summary>
		''' Method which raises an event based on the call state.
		''' </summary>
		''' <param name="iTCallInfo">ITCallInfo interface.</param>
		''' <param name="callState">Call state.</param>
		Private Sub CallEventMethod(ByVal iTCallInfo As ITCallInfo, ByVal callState As CALL_STATE)
			Dim [call] As CallInfo = TapiBase.GetCallDetails(iTCallInfo)

			Select Case iTCallInfo.CallState
				Case CALL_STATE.CS_INPROGRESS
					[call].callInitiateTime_Renamed = DateTime.Now
					[call].callDirection_Renamed = CallDirection.Outgoing
					Me.availableCalls_Renamed.Add([call])
					' Make the dialed call as current call.
					Me.currentCall_Renamed = [call]
					Me.iTCurrentCallInfo = iTCallInfo

				Case CALL_STATE.CS_OFFERING
					[call].callInitiateTime_Renamed = DateTime.Now
					[call].callDirection_Renamed = CallDirection.Incoming
					Me.availableCalls_Renamed.Add([call])

				Case CALL_STATE.CS_CONNECTED
					Dim i As Integer = 0
					Do While i < Me.availableCalls_Renamed.Count
						' Set the start time.
						If Me.availableCalls_Renamed(i).hashCode = [call].hashCode Then
							[call].startTime_Renamed = DateTime.Now
							[call].callInitiateTime_Renamed = Me.availableCalls_Renamed(i).callInitiateTime_Renamed
							[call].callDirection_Renamed = Me.availableCalls_Renamed(i).callDirection_Renamed
							Me.availableCalls_Renamed.RemoveAt(i)
							Me.availableCalls_Renamed.Add([call])
							Me.currentCall_Renamed = [call]
							Me.iTCurrentCallInfo = iTCallInfo
							Exit Do
						End If
						i += 1
					Loop

				Case CALL_STATE.CS_DISCONNECTED
					Dim i As Integer = 0
					Do While i < Me.availableCalls_Renamed.Count
						If Me.availableCalls_Renamed(i).hashCode = [call].hashCode Then
							' Set call end time.
							[call].startTime_Renamed = Me.availableCalls_Renamed(i).startTime_Renamed
							[call].callInitiateTime_Renamed = Me.availableCalls_Renamed(i).callInitiateTime_Renamed
							[call].callDirection_Renamed = Me.availableCalls_Renamed(i).callDirection_Renamed
							[call].endTime_Renamed = DateTime.Now
							Me.availableCalls_Renamed.RemoveAt(i)
							Me.currentCall_Renamed = Nothing
							Me.iTCurrentCallInfo = Nothing
							Exit Do
						End If
						i += 1
					Loop

				Case CALL_STATE.CS_HOLD
					Dim i As Integer = 0
					Do While i < Me.availableCalls_Renamed.Count
						If Me.availableCalls_Renamed(i).hashCode = [call].hashCode Then
							[call].callDirection_Renamed = Me.availableCalls_Renamed(i).callDirection_Renamed
							Me.availableCalls_Renamed.RemoveAt(i)
							Me.availableCalls_Renamed.Add([call])
							Me.currentCall_Renamed = [call]
							Me.iTCurrentCallInfo = iTCallInfo
							Exit Do
						End If
						i += 1
					Loop
			End Select

			If callState = CALL_STATE.CS_OFFERING Then
				RaiseEvent OnIncomingCall([call])
			ElseIf callState = CALL_STATE.CS_INPROGRESS Then
				RaiseEvent OnOutgoingCall([call])
			ElseIf callState = CALL_STATE.CS_CONNECTED Then
				RaiseEvent OnCallConnected([call])
			ElseIf callState = CALL_STATE.CS_DISCONNECTED Then
				RaiseEvent OnCallDisconnected([call])
			ElseIf callState = CALL_STATE.CS_HOLD Then
				RaiseEvent OnCallHold([call])
			End If
		End Sub

		''' <summary>
		''' Extracts the call details from ITCallInfo interface.
		''' </summary>
		''' <param name="iTCallInfo">ITCallInfo interface.</param>
		''' <returns>Call details.</returns>
		Private Shared Function GetCallDetails(ByVal iTCallInfo As ITCallInfo) As CallInfo
			Dim [call] As CallInfo = New CallInfo()

			Try
				[call].callerId_Renamed = iTCallInfo.CallInfoString(CALLINFO_STRING.CIS_CALLERIDNAME)
			Catch
				Try
					[call].callerId_Renamed = iTCallInfo.CallInfoString(CALLINFO_STRING.CIS_CALLERIDNUMBER)
				Catch
					[call].callerId_Renamed = String.Empty
				End Try
			End Try

			Try
				[call].calledId_Renamed = iTCallInfo.CallInfoString(CALLINFO_STRING.CIS_CALLEDIDNAME)
			Catch
				Try
					[call].calledId_Renamed = iTCallInfo.CallInfoString(CALLINFO_STRING.CIS_CALLEDIDNUMBER)
				Catch
					[call].calledId_Renamed = String.Empty
				End Try
			End Try

			[call].callState_Renamed = CType(iTCallInfo.CallState, CallState)
			[call].hashCode = CType(iTCallInfo, Object).GetHashCode()
			[call].lineName_Renamed = iTCallInfo.Address.AddressName
			Return [call]
		End Function

		''' <summary>
		''' Gets the ITCallInfo interface based on the specified call.
		''' </summary>
		''' <param name="call">Call details.</param>
		''' <returns>ITCallInfo interface if match found, else returns null.</returns>
		Private Function ConvertToCallInfoObject(ByVal [call] As CallInfo) As ITCallInfo
			' Get the available address lines with audio support.
			Dim addressLines As List(Of Line) = GetAvailableLines()

			For Each addressLine As Line In addressLines
				Dim iTAddress As ITAddress = GetLineObject(addressLine.lineName_Renamed)

				If String.Equals(iTAddress.AddressName, [call].lineName_Renamed) Then
					Dim iEnumCall As IEnumCall = iTAddress.EnumerateCalls()

					Dim callsFetched As UInteger = 0
					Dim iTCallInfo As ITCallInfo = Nothing
					Try
						Do
							' Enumerate calls on the address line.
							iEnumCall.Next(1, iTCallInfo, callsFetched)
							If iTCallInfo Is Nothing Then
								Exit Do
							End If
							If CType(iTCallInfo, Object).GetHashCode() = [call].hashCode Then
								Return iTCallInfo
							End If
						Loop
					Catch
						' Do nothing. Check the next address line.
					End Try
				End If
			Next addressLine
			Return Nothing
		End Function

		''' <summary>
		''' TAPI calls this method when an event occurs.
		''' </summary>
		''' <param name="tapiEvent">TapiEvent.</param>
		''' <param name="pEvent">Object associated with the event.</param>
		Private Sub [Event](ByVal tapiEvent As TAPI_EVENT, ByVal pEvent As Object)
			Select Case tapiEvent
				Case TAPI_EVENT.TE_DIGITEVENT
					Dim iTDigitDetectionEvent As ITDigitDetectionEvent = CType(pEvent, ITDigitDetectionEvent)
                    Dim digit As Char = Chr(iTDigitDetectionEvent.Digit)
					RaiseEvent OnDigitReceived(Me.currentCall_Renamed, digit)

				Case TAPI_EVENT.TE_CALLSTATE
					Dim iTCallStateEvent As ITCallStateEvent = CType(pEvent, ITCallStateEvent)

					Dim iTCallInfo As ITCallInfo = iTCallStateEvent.Call

					Select Case iTCallInfo.CallState
						Case CALL_STATE.CS_INPROGRESS
							CallEventMethod(iTCallInfo, CALL_STATE.CS_INPROGRESS)

						Case CALL_STATE.CS_CONNECTED
							CallEventMethod(iTCallInfo, CALL_STATE.CS_CONNECTED)

						Case CALL_STATE.CS_DISCONNECTED
							Dim iTBasicCallControl2 As ITBasicCallControl2 = CType(iTCallInfo, ITBasicCallControl2)
							If Not Me.fileRecordingTerminal Is Nothing Then
								Dim mediaControl As ITMediaControl = CType(Me.fileRecordingTerminal, ITMediaControl)
								mediaControl.Stop()
							End If
							CallEventMethod(iTCallInfo, CALL_STATE.CS_DISCONNECTED)

						Case CALL_STATE.CS_OFFERING
							CallEventMethod(iTCallInfo, CALL_STATE.CS_OFFERING)

						Case CALL_STATE.CS_HOLD
							CallEventMethod(iTCallInfo, CALL_STATE.CS_HOLD)
					End Select
				Case TAPI_EVENT.TE_FILETERMINAL
					Dim iTFileTerminalEvent As ITFileTerminalEvent = CType(pEvent, ITFileTerminalEvent)
					If iTFileTerminalEvent.Cause = FT_STATE_EVENT_CAUSE.FTEC_END_OF_FILE Then
						RaiseEvent OnEndOfFilePlayback(Me.currentCall_Renamed)
					End If
			End Select
		End Sub

		''' <summary>
		''' Registers an address line for tapi call events.
		''' </summary>
		''' <param name="iTAddress">ITAddress interface of the line to be registered.</param>
		''' <returns>True if the method succeeds.</returns>
		Private Function RegisterLineForIncomingCalls(ByVal iTAddress As ITAddress) As Boolean
			Try
				Dim registrationToken As Integer = Me.tapiObject.RegisterCallNotifications(iTAddress, True, True, TapiConstants.TAPIMEDIATYPE_AUDIO, 1)
				Me.registrationTokens.Add(registrationToken)
			Catch
				Return False
			End Try
			Return True
		End Function

		''' <summary>
		''' Selects the media terminals on the specified call.
		''' </summary>
		''' <param name="iTBasicCallControl">ITBasicCallControl interface.</param>
		''' <param name="iTAddress">ITAddress interface.</param>
		''' <returns>True if the method succeeds.</returns>
		Private Shared Function SelectMediaTerminals(ByVal iTBasicCallControl As ITBasicCallControl, ByVal iTAddress As ITAddress) As Boolean
			If TapiBase.SelectStaticCaptureTerminal(iTBasicCallControl, iTAddress) = False OrElse TapiBase.SelectStaticRenderTerminal(iTBasicCallControl, iTAddress) = False Then
				Return False
			Else
				Return True
			End If
		End Function

		''' <summary>
		''' Unselects the media terminals on the specified call.
		''' </summary>
		''' <param name="iTBasicCallControl">ITBasicCallControl interface.</param>
		''' <param name="iTAddress">ITAddress interface.</param>
		''' <returns>True if the method succeeds.</returns>
		Private Shared Function UnselectMediaTerminals(ByVal iTBasicCallControl As ITBasicCallControl, ByVal iTAddress As ITAddress) As Boolean
			If TapiBase.UnselectStaticCaptureTerminal(iTBasicCallControl, iTAddress) = False OrElse TapiBase.UnselectStaticRenderTerminal(iTBasicCallControl, iTAddress) = False Then
				Return False
			Else
				Return True
			End If
		End Function

		''' <summary>
		''' Selects the static terminal on the specified call.
		''' </summary>
		''' <param name="iTBasicCallControl">ITBasicCallControl interface.</param>
		''' <param name="iTAddress">ITAddress interface.</param>
		''' <returns>True if the method succeeds.</returns>
		Private Shared Function SelectStaticCaptureTerminal(ByVal iTBasicCallControl As ITBasicCallControl, ByVal iTAddress As ITAddress) As Boolean
			Try
				Dim iEnumStream As IEnumStream = Nothing
				Dim iTStreamControl As ITStreamControl = Nothing

				iTStreamControl = CType(iTBasicCallControl, ITStreamControl)

				iTStreamControl.EnumerateStreams(iEnumStream)
				Dim iTStream As ITStream
				Dim streamsFetched As UInteger = 0
				Do
					iEnumStream.Next(1, iTStream, streamsFetched)
					If iTStream Is Nothing Then
						Exit Do
					End If
					If iTStream.Direction = TERMINAL_DIRECTION.TD_CAPTURE Then
						Dim iTTerminalSupport As ITTerminalSupport = CType(iTAddress, ITTerminalSupport)
						Dim iTTerminal As ITTerminal = iTTerminalSupport.GetDefaultStaticTerminal(iTStream.MediaType, iTStream.Direction)

						If iTTerminal.State = TERMINAL_STATE.TS_NOTINUSE Then
							iTStream.SelectTerminal(iTTerminal)
							Return True
						End If
					End If
				Loop
			Catch
				Return False
			End Try
			Return False
		End Function

		''' <summary>
		''' Selects the static terminal on the specified call.
		''' </summary>
		''' <param name="iTBasicCallControl">ITBasicCallControl interface.</param>
		''' <param name="iTAddress">ITAddress interface.</param>
		''' <returns>True if the method succeeds.</returns>
		Private Shared Function SelectStaticRenderTerminal(ByVal iTBasicCallControl As ITBasicCallControl, ByVal iTAddress As ITAddress) As Boolean
			Try
				Dim iEnumStream As IEnumStream = Nothing
				Dim iTStreamControl As ITStreamControl = Nothing

				iTStreamControl = CType(iTBasicCallControl, ITStreamControl)

				iTStreamControl.EnumerateStreams(iEnumStream)
				Dim iTStream As ITStream
				Dim streamsFetched As UInteger = 0
				Do
					iEnumStream.Next(1, iTStream, streamsFetched)
					If iTStream Is Nothing Then
						Exit Do
					End If
					If iTStream.Direction = TERMINAL_DIRECTION.TD_RENDER Then
						Dim iTTerminalSupport As ITTerminalSupport = CType(iTAddress, ITTerminalSupport)
						Dim iTTerminal As ITTerminal = iTTerminalSupport.GetDefaultStaticTerminal(iTStream.MediaType, iTStream.Direction)

						If iTTerminal.State = TERMINAL_STATE.TS_NOTINUSE Then
							iTStream.SelectTerminal(iTTerminal)
							Return True
						End If
					End If
				Loop
			Catch
				Return False
			End Try
			Return False
		End Function

		''' <summary>
		''' Unselects the static terminal on the specified call.
		''' </summary>
		''' <param name="iTBasicCallControl">ITBasicCallControl interface.</param>
		''' <param name="iTAddress">ITAddress interface.</param>
		''' <returns>True if the method succeeds.</returns>
		Private Shared Function UnselectStaticCaptureTerminal(ByVal iTBasicCallControl As ITBasicCallControl, ByVal iTAddress As ITAddress) As Boolean
			Try
				Dim iEnumStream As IEnumStream = Nothing
				Dim iTStreamControl As ITStreamControl = Nothing

				iTStreamControl = CType(iTBasicCallControl, ITStreamControl)

				iTStreamControl.EnumerateStreams(iEnumStream)
				Dim iTStream As ITStream
				Dim streamsFetched As UInteger = 0
				Do
					iEnumStream.Next(1, iTStream, streamsFetched)
					If iTStream Is Nothing Then
						Exit Do
					End If
					If iTStream.Direction = TERMINAL_DIRECTION.TD_CAPTURE Then
						Dim iTTerminalSupport As ITTerminalSupport = CType(iTAddress, ITTerminalSupport)
						Dim iTTerminal As ITTerminal = iTTerminalSupport.GetDefaultStaticTerminal(iTStream.MediaType, iTStream.Direction)
						iTStream.UnselectTerminal(iTTerminal)
						Return True
					End If
				Loop
			Catch
				Return False
			End Try
			Return False
		End Function

		''' <summary>
		''' Unselects the static terminal on the specified call.
		''' </summary>
		''' <param name="iTBasicCallControl">ITBasicCallControl interface.</param>
		''' <param name="iTAddress">ITAddress interface.</param>
		''' <returns>True if the method succeeds.</returns>
		Private Shared Function UnselectStaticRenderTerminal(ByVal iTBasicCallControl As ITBasicCallControl, ByVal iTAddress As ITAddress) As Boolean
			Try
				Dim iEnumStream As IEnumStream = Nothing
				Dim iTStreamControl As ITStreamControl = Nothing

				iTStreamControl = CType(iTBasicCallControl, ITStreamControl)

				iTStreamControl.EnumerateStreams(iEnumStream)
				Dim iTStream As ITStream
				Dim streamsFetched As UInteger = 0
				Do
					iEnumStream.Next(1, iTStream, streamsFetched)
					If iTStream Is Nothing Then
						Exit Do
					End If
					If iTStream.Direction = TERMINAL_DIRECTION.TD_RENDER Then
						Dim iTTerminalSupport As ITTerminalSupport = CType(iTAddress, ITTerminalSupport)
						Dim iTTerminal As ITTerminal = iTTerminalSupport.GetDefaultStaticTerminal(iTStream.MediaType, iTStream.Direction)
						iTStream.UnselectTerminal(iTTerminal)
						Return True
					End If
				Loop
			Catch
				Return False
			End Try
			Return False
		End Function

		#End Region

	End Class

End Namespace
